package com.jweb.framework.security.pass;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.security.MessageDigest;
import java.util.ResourceBundle;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：解密
 */
public class DecryptPass implements IDecryptPass {
	
	private Cipher encip ;
	private Cipher decip ;
	private Cipher encip1 ;
	private Cipher decip1 ;
	private String desKey ;
	private String dateKey ;
	
	private final String Algorithm = "DESede";
	final byte initkeyBytes[] = { 18, 52, 86, 120, 9, -85, -51, -17, -2, -36,
			-70, -112, -121, 101, 67, 33, -17, -51, -85, 9, 120, 86, 52, 18 };
	
	public String decryptStr(String in) {
		try {
			return new String(this.decip.doFinal(asc2bcd(in)));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return null ;
	}
	
	public String getDePass(String hostIp , String accName) throws FileNotFoundException , IOException , Exception {
		String enPass = getEnPassFromFile(hostIp , accName) ;
		init3DES();
		String dePass = decryptStr(enPass);
		return dePass ;
	}
	
	private boolean init3DES(){
		Global.desKey = "CAB664DCC2FE67712919C274B11DD4D456E6BBC10F6D7E64DC0DB194A3EC6261";
		if(Global.desKey != null) {
			this.desKey = Global.desKey ;
		}
		try {
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(this.Algorithm);
			DESedeKeySpec desKeySpec1 = new DESedeKeySpec(this.initkeyBytes);
			javax.crypto.SecretKey desKey1 = keyFactory.generateSecret(desKeySpec1);
			this.encip1 = Cipher.getInstance(this.Algorithm);
			this.decip1 = Cipher.getInstance(this.Algorithm);
			this.encip1.init(1, desKey1);
			this.decip1.init(2, desKey1);
			
			byte[] keyBytes = md5Buffer(decrypt1Str(this.dateKey)).getBytes();
			DESedeKeySpec desKeySpec2 = new DESedeKeySpec(keyBytes);
			javax.crypto.SecretKey desKey2 = keyFactory.generateSecret(desKeySpec2);
			this.encip = Cipher.getInstance(this.Algorithm);
			this.decip = Cipher.getInstance(this.Algorithm);
			this.encip.init(1, desKey2);
			this.decip.init(2, desKey2);
			
		} catch (Exception e) {
			e.printStackTrace() ;
			return false ;
		}
		
		return true ;
	}
	
	public String decrypt1Str(String in){
		try {
			return new String(this.decip1.doFinal(asc2bcd(in)));
		} catch (Exception e) {
			e.printStackTrace() ;
		}
		return null ;
	}
	
	private String getEnPassFromFile(String hostIp , String accName) throws FileNotFoundException , IOException , Exception {
		try {
			InputStream is = this.getClass().getClassLoader().getResourceAsStream("properties/dbpasswd.properties");
			InputStreamReader isReader = new InputStreamReader(is);
			LineNumberReader read = new LineNumberReader(isReader);
			String enPass = read.readLine();
			if(enPass != null && !enPass.startsWith((new StringBuilder(String.valueOf(hostIp))).append(":").append(accName).append(":").toString())){
				enPass = read.readLine();
			}
            if(enPass == null){
            	throw new Exception("the request password not found");
            }
            String enPassArr[] = enPass.split(":");
            boolean isMd5Ok = md5StrOk((new StringBuilder(String.valueOf(enPassArr[0]))).append(":").append(enPassArr[1]).append(":").append(enPassArr[2]).append(":").append(enPassArr[3]).toString(), enPassArr[4]);
            if(!isMd5Ok){
            	throw new Exception("the password file is changed");
            }
            else {
            	read.close();
            	this.dateKey = enPassArr[2];
            	return enPassArr[3];
            }
                
		} catch (FileNotFoundException e) {
			e.printStackTrace() ;
			throw e ;
		}
		catch (IOException ioe){
			ioe.printStackTrace();
			throw ioe ;
		}
	}
	
	private boolean md5StrOk(String from , String md5){
		if(md5 == null){
			return false ;
		}
		else {
			return md5Buffer(from).equals(md5);
		}
	}
	
	private String md5Buffer(String strSrc){
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(strSrc.getBytes());
			return bcd2asc(md.digest());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null ;
	}
	
	private String bcd2asc(byte b[]){
		String hs = "";
        String stmp = "";
        for(int n = 0; n < b.length; n++)
        {
            stmp = Integer.toHexString(b[n] & 255);
            if(stmp.length() == 1)
                hs = (new StringBuilder(String.valueOf(hs))).append("0").append(stmp).toString();
            else
                hs = (new StringBuilder(String.valueOf(hs))).append(stmp).toString();
        }

        return hs.toUpperCase();
	}
	
	private String getFileName() {
		ResourceBundle bundle = ResourceBundle.getBundle("properties/config");
		String passFile = bundle.getString("passfile");
		return passFile ;
	}
	
	private byte[] asc2bcd(String hexstr){
		if (hexstr.length() % 2 != 0){
			hexstr = (new StringBuilder(String.valueOf(hexstr))).append("0").toString();
		}
		byte bytes[] = new byte[hexstr.length() / 2];
		for (int i = 0; i < hexstr.length() / 2; i++) {
			byte temp[] = new byte[2];
			temp[0] = (byte) hexstr.charAt(i * 2);
			temp[1] = (byte) hexstr.charAt(i * 2 + 1);
			bytes[i] = (byte) Integer.parseInt(new String(temp), 16);
		}
		return bytes;
	}

	@Override
	public String getDePass(JdbcTemplate jdbcTemplate , String securityId)
			throws FileNotFoundException, IOException, Exception {
		throw new UnsupportedOperationException() ;
	}
	
}
